import { defineStore } from "pinia";
import { store, router, resetRouter, routerArrays } from "../utils";
import {
  getToken,
  setToken,
  removeToken,
  setUser,
  setRoles,
  setPermissions,
  removeRoles,
  removeUser,
  removePermissions
} from "@/utils/auth";

import { login, logout } from "@/api/user/oauth2";
import { userInfo, userSelect } from "@/api/user/user";
import type {
  Login,
  OAuth2,
  PermissionData,
  RoleData,
  UserData
} from "@/api/user";
import { rolePermission } from "@/api/user/rbac";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";

export const useUserStore = defineStore({
  id: "user",
  state: () => ({
    user: null as unknown as UserData,
    roles: null as unknown as string[],
    permissions: null as unknown as string[],
    userMap: new Map<string, UserData>()
  }),
  actions: {
    setUser(userData: UserData) {
      this.user = userData;
      setUser(userData);
    },

    setRoles(roles: string[]) {
      this.roles = roles;
      setRoles(roles);
    },

    setPermissions(permissions: string[]) {
      this.permissions = permissions;
      setPermissions(permissions);
    },

    async getUser() {
      if (this.user) {
        return this.user;
      }
      const token = getToken();
      if (token) {
        await this.userInfo();
        return this.user;
      }
      return null as unknown as UserData;
    },

    async getRoles() {
      if (this.roles) {
        return this.roles;
      }
      const token = getToken();
      if (token) {
        await this.rolePermission();
        return this.roles;
      }
      return null as unknown as string[];
    },

    async getPermissions() {
      if (this.permissions) {
        return this.permissions;
      }
      const token = getToken();
      if (token) {
        await this.rolePermission();
        return this.permissions;
      }
      return null as unknown as string[];
    },

    async login(param: Login) {
      await login({ param }).then(({ data }) => {
        const oAuth2: OAuth2 = data;
        setToken(oAuth2);
      });
      await this.userInfo();
      await this.rolePermission();
    },

    async userInfo() {
      await userInfo({ param: {} }).then(({ data }) => {
        const user: UserData = data;
        this.setUser(user);
      });
    },

    async rolePermission() {
      await rolePermission({ param: {} }).then(({ data }) => {
        const roleDataList: RoleData[] = data.roleDataList;
        const roles = roleDataList.map(v => v.code);
        this.setRoles(roles);
        const permissionDataList: PermissionData[] = data.permissionDataList;
        const permissions = permissionDataList.map(v => v.code);
        this.setPermissions(permissions);
      });
    },

    async logout() {
      await logout({ param: {} });
      removeToken();
      this.user = null as unknown as UserData;
      this.roles = null as unknown as string[];
      this.permissions = null as unknown as string[];
      removeUser();
      removeRoles();
      removePermissions();
      useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
      resetRouter();
      await router.push("/login");
    },

    async userSelect(id: string): Promise<UserData> {
      const user = this.userMap.get(id);
      if (user) {
        return user as UserData;
      }
      await userSelect({ param: { id } }).then(({ data }) => {
        const user: UserData = data;
        this.userMap.set(id, user);
      });
      return this.userMap.get(id) as UserData;
    }
  }
});

export function useUserStoreHook() {
  return useUserStore(store);
}
